/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ProOF.apl.problems.real;

import ProOF.apl.methods.GA.population.aPopulation;
import ProOF.apl.problems.real.functions.aRealFunction;
import ProOF.com.Communication;
import ProOF.com.LinkerNodes;
import ProOF.com.LinkerParameters;
import ProOF.com.LinkerResults;
import ProOF.com.LinkerValidations;
import ProOF.com.StreamProgress;
import ProOF.gen.best.BestSol;
import ProOF.gen.best.nEvaluations;
import ProOF.gen.stopping.aStop;
import ProOF.opt.abst.problem.meta.Solution;
import ProOF.opt.abst.problem.meta.objective.SingleObjective;
import java.util.ArrayList;

/**
 *
 * @author hossomi
 */
public final class iStopNoImprove extends aStop{
    public static final iStopNoImprove obj = new iStopNoImprove();
    
    private BestSol             best;
    private Solution            lastBest;
    private aPopulation         pop;
    private StreamProgress      prog;
    
    private int     maxFails;
    private double  minImprove;
    
    private int     fails;
    private double  improve;
    
    @Override
    public String name() {
        return "Stop for no Improve";
    }
    
    @Override
    public String description() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void services(LinkerNodes win) throws Exception {
        best = win.need(BestSol.class, best);
        pop = win.need(aPopulation.class, pop);
    }
    
    @Override
    public void parameters(LinkerParameters win) throws Exception {
        maxFails = win.Int("Stop Max Fails", 3000, 100, 100000);
        minImprove = win.Dbl("Stop Min Improve", 0.0001, 0, 1);
    }
    
    @Override
    public void load() throws Exception {
        prog = Communication.mkProgress("Improvement Convergence");
    }

    @Override
    public void start() throws Exception {
        super.start();
        lastBest = null;
        fails = 0;
        improve = 0;
    }
    
    @Override
    public boolean validation(LinkerValidations win) throws Exception {
        return true;
    }
    
    @Override
    public double progress() throws Exception {
        if (lastBest == null || pop.getIndividuals().size() < pop.getSize()) {
            prog.progress(0);
            return 0;
        }
        
        double improveFactor = (improve - minImprove)/improve;
        double failFactor = fails*1.0/maxFails * improveFactor;
        double factor = 1 - improveFactor + failFactor;
        
        prog.progress(factor);
        return factor;
    }  
    
    @Override
    public boolean end() throws Exception {
        Solution newBest = best.ind();
        
        if (lastBest == null || pop.getIndividuals().size() < pop.getSize()) {
            lastBest = newBest;
            return false;
        }
        
        if (newBest == lastBest) {
            fails++;
            progress();
            
            /*if (fails >= maxFails) {
                fails = 0;
                throw new ExceptionForceReinit();
            }*/
            
            return fails >= maxFails;
        }

        double lastFitness = ((SingleObjective)lastBest.obj()).abs_value();
        double newFitness = ((SingleObjective)newBest.obj()).abs_value();
        
        fails = 0;
        improve = Math.abs((lastFitness - newFitness) / lastFitness);
        
        lastBest = newBest;
        
        progress();
        return improve < minImprove;
    }

    @Override
    public void results(LinkerResults com) throws Exception {
        super.results(com);
    }
}
